package com.senlingspace.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * AES 加密/解密
 *
 * @author lebronjames
 */
@Slf4j
public class AesUtil {

    private final static String KEY_ALGORITHMS = "AES";
    private final static int KEY_SIZE = 128;

    /**
     * 该秘钥用于用户小程序核销二维码
     * <p>
     * 禁止修改
     */
    private static final String QRCODE_SECRET_KEY = "2R7aLWxn06SkibmI1bcr0w==";

    private AesUtil() {
    }

    /**
     * 生成AES密钥，base64编码格式 (128)
     *
     * @return
     * @throws Exception
     */
    public static String getKeyAES128() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHMS);
        keyGen.init(KEY_SIZE);
        SecretKey key = keyGen.generateKey();
        return Base64.encodeBase64String(key.getEncoded());
    }

    /**
     * 根据base64Key获取SecretKey对象
     *
     * @param base64Key
     * @return
     */
    public static SecretKey loadKeyAES(String base64Key) {
        byte[] bytes = Base64.decodeBase64(base64Key);
        return new SecretKeySpec(bytes, KEY_ALGORITHMS);
    }

    /**
     * AES 加密字符串，SecretKey对象
     *
     * @param key
     * @param encryptData
     * @param encode
     * @return
     */
    public static String encrypt(SecretKey key, String encryptData, String encode) {
        try {
            final Cipher cipher = Cipher.getInstance(KEY_ALGORITHMS);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptBytes = encryptData.getBytes(encode);
            byte[] result = cipher.doFinal(encryptBytes);
            return Base64.encodeBase64String(result);
        } catch (Exception e) {
            log.error("加密异常:" + e.getMessage());
            return null;
        }
    }

    /**
     * AES 加密字符串，base64Key对象
     *
     * @param base64Key
     * @param encryptData
     * @param encode
     * @return
     */
    public static String encrypt(String base64Key, String encryptData, String encode) {
        SecretKey key = loadKeyAES(base64Key);
        try {
            final Cipher cipher = Cipher.getInstance(KEY_ALGORITHMS);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptBytes = encryptData.getBytes(encode);
            byte[] result = cipher.doFinal(encryptBytes);
            return Base64.encodeBase64String(result);
        } catch (Exception e) {
            log.error("加密异常:" + e.getMessage());
            return null;
        }
    }

    /**
     * AES 解密字符串，SecretKey对象
     *
     * @param key
     * @param decryptData
     * @param encode
     * @return
     */
    public static String decrypt(SecretKey key, String decryptData, String encode) {
        try {
            final Cipher cipher = Cipher.getInstance(KEY_ALGORITHMS);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decryptBytes = Base64.decodeBase64(decryptData);
            byte[] result = cipher.doFinal(decryptBytes);
            return new String(result, encode);
        } catch (Exception e) {
            log.error("加密异常:" + e.getMessage());
            return null;
        }
    }

    /**
     * AES 解密字符串，base64Key对象
     *
     * @param base64Key
     * @param decryptData
     * @param encode
     * @return
     */
    public static String decrypt(String base64Key, String decryptData, String encode) {
        SecretKey key = loadKeyAES(base64Key);
        try {
            final Cipher cipher = Cipher.getInstance(KEY_ALGORITHMS);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decryptBytes = Base64.decodeBase64(decryptData);
            byte[] result = cipher.doFinal(decryptBytes);
            return new String(result, encode);
        } catch (Exception e) {
            log.error("加密异常:" + e.getMessage());
            return null;
        }
    }

    /**
     * 小程序核销二维码加密
     *
     * @param encryptData
     * @return {@link String }
     */
    public static String encryptQrcode(String encryptData) {
        return encrypt(QRCODE_SECRET_KEY, encryptData, StandardCharsets.UTF_8.displayName());
    }

    /**
     * 小程序核销二维码解密
     *
     * @param encryptData
     * @return {@link String }
     */
    public static String decryptQrcode(String encryptData) {
        return decrypt(QRCODE_SECRET_KEY, encryptData, StandardCharsets.UTF_8.displayName());
    }

    /**
     * 生成随机盐
     *
     * @return 随机盐
     */
    public static String generateSalt() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

}
